#include <sys/socket.h>
#include <netinet/in.h>
#include <string.h>
#include <unistd.h>

#include <X11/Xlib.h>
#include <X11/keysym.h>
#include <stdio.h>
#include <cerrno>
#include <thread>
#include <stdlib.h>
#include <arpa/inet.h>
#include <csignal>
#include <queue>
#include <mutex>
#include <chrono>
#include <iostream>
#include <pthread.h>
#include <fstream>
#include <sstream>
#include <map>
#include "IniFileParser.h"
#include <memory>

// #include "remote_control.h"

std::queue<XEvent> g_queEventQueue;
std::mutex g_mtxEventQueueMutex;
unsigned int g_uiEventQueueSize = 20;
std::string g_strServerIP;
uint16_t g_usServerPort;

std::pair<bool, XEvent> popEvent()
{
    XEvent ei;
    // 从队列中弹出事件
    std::lock_guard<std::mutex> lock(g_mtxEventQueueMutex);
    if (g_queEventQueue.empty())
    {
        return std::make_pair(false, ei);
    }
    ei = g_queEventQueue.front();
    g_queEventQueue.pop();
    return std::make_pair(true, ei);
}
void pushEvent(XEvent ei)
{
    // 将事件推入队列
    std::lock_guard<std::mutex> lock(g_mtxEventQueueMutex);
    if (g_queEventQueue.size() >= g_uiEventQueueSize)
    {
        g_queEventQueue.pop();
    }
    g_queEventQueue.push(ei);
}

// 信号处理的全局标志
volatile sig_atomic_t shutdown_requested = 0;

// 信号处理函数
void signal_handler(int signum)
{
    std::cout << "捕获到信号 " << signum << std::endl;
    shutdown_requested = 1;
}

int connectToServer(uint16_t hostport)
{
    int sock = socket(AF_INET, SOCK_STREAM, 0);
    if (sock < 0)
    {
        perror("socket creation failed");
        return -1;
    }

    struct sockaddr_in serv_addr;
    memset(&serv_addr, 0, sizeof(serv_addr));
    serv_addr.sin_family = AF_INET;
    serv_addr.sin_port = htons(hostport); // 服务器端口号

    // 将IPv4地址从文本转换为二进制形式
    if (inet_pton(AF_INET, g_strServerIP.c_str(), &serv_addr.sin_addr) <= 0)
    {
        std::cerr << "Invalid address/ Address not supported" << std::endl;
        close(sock);
        return -1;
    }

    if (connect(sock, (struct sockaddr *)&serv_addr, sizeof(serv_addr)) < 0)
    {
        std::cerr << "Connection Failed" << std::endl;
        close(sock);
        return -2;
    }
    std::cout << "Connected to server" << std::endl;
    return sock;
}
// 发送函数，确保所有数据都发送出去
int sendEventToServer(const void *event, size_t size)
{
    int sock = connectToServer(g_usServerPort);
    if (sock < 0)
    {
        return -1;
    }
    const char *ptr = (const char *)event;
    size_t remaining = size;

    while (remaining > 0)
    {
        ssize_t bytes_sent = send(sock, ptr, remaining, 0);

        if (bytes_sent < 0)
        {
            if (errno == EINTR)
            {
                continue;
            }
            std::cerr << "send failed" << std::endl;
            close(sock);
            return -1;
        }
        // 更新已发送数据的指针和剩余字节数
        ptr += bytes_sent;
        remaining -= bytes_sent;
    }
    close(sock);
    return 0;
}

// 处理鼠标键盘事件的函数
void *handleXEvent(void *arg)
{
    XEvent event;

    while (0 == shutdown_requested)
    {
        std::pair<bool, XEvent> eventPair = popEvent();
        if (eventPair.first)
        {
            event = eventPair.second;
            if (event.type != 0)
            {
                std::cout << "event type: " << event.type << std::endl;
                sendEventToServer(&event, sizeof(event));
            }
        }
        std::this_thread::sleep_for(std::chrono::milliseconds(10));
    }
    std::cout << "handleXEvent thread exit" << std::endl;
    return NULL;
}
bool checkMouseEvent(Display *display, XEvent *event, Window window)
{
    return true; // event->type == ButtonPress && event->xbutton.window == window;
}
// 捕获鼠标键盘事件的函数
void *captureXEvent(void *arg)
{

    Display *display = XOpenDisplay(NULL);
    if (display == NULL)
    {
        std::cerr << "Could not open display" << std::endl;
        return NULL;
    }

    int screen = DefaultScreen(display);
    Window window = XCreateSimpleWindow(display, RootWindow(display, screen), 10, 10, 640, 480, 1,
                                        BlackPixel(display, screen), WhitePixel(display, screen));
    if (window == 0)
    {
        std::cerr << "Failed to create window." << std::endl;
        XCloseDisplay(display);
        return NULL;
    }

    XSelectInput(display, window, ButtonPressMask | ButtonReleaseMask | KeyPressMask | KeyReleaseMask | PointerMotionMask);

    XMapWindow(display, window);
    XFlush(display);

    XEvent event;
    while (0 == shutdown_requested)
    {
        // 等待事件
        XNextEvent(display, &event); // 阻塞型
        // if (XCheckIfEvent(display, &event, NULL, (XPointer)window)) // 非阻塞型
        {
            // std::cout << "event type: " << event.type << std::endl;
            pushEvent(event);
        }
        std::this_thread::sleep_for(std::chrono::milliseconds(10));
    }

    XCloseDisplay(display);
    std::cout << "captureXEvent thread exit" << std::endl;
    return NULL;
}

int main()
{
    signal(SIGINT, signal_handler); // 注册信号处理函数
    // IniFileParser iniParser("../config.ini");
    std::shared_ptr<IniFileParser> iniParserPtr = std::make_shared<IniFileParser>("../config.ini");
    if (!iniParserPtr->getStrValue("ip", g_strServerIP))
    {
        return EXIT_FAILURE;
    }
    std::cout << "ip: " << g_strServerIP << std::endl;

    int port;
    if (!iniParserPtr->getIntValue("port", port))
    {
        return EXIT_FAILURE;
    }
    if (port < 0 || port > std::numeric_limits<uint16_t>::max())
    {
        std::cerr << "Invalid port number " << port << std::endl;
        return EXIT_FAILURE;
    }
    else if (port > 0 && port < 1024) // 知名端口，通常被IANA（互联网号码分配机构）分配给一些公认的服务
    {
        std::cerr << "port number " << port << " is not available." << std::endl;
        return EXIT_FAILURE;
    }
    else
    {
        g_usServerPort = static_cast<uint16_t>(port);
    }
    std::cout << "port: " << g_usServerPort << std::endl;

    pthread_t capture_event_thread, handle_event_thread;

    // 创建键盘事件捕获线程
    if (pthread_create(&capture_event_thread, NULL, captureXEvent, NULL) != 0)
    {
        // XCloseDisplay(display);
        std::cerr << "Connection Failed" << std::endl;
        return EXIT_FAILURE;
    }

    // 创建处理鼠标键盘事件线程
    if (pthread_create(&handle_event_thread, NULL, handleXEvent, NULL) != 0)
    {
        // XCloseDisplay(display);
        std::cerr << "Connection Failed" << std::endl;
        return EXIT_FAILURE;
    }

    pthread_join(capture_event_thread, NULL);
    pthread_join(handle_event_thread, NULL);

    // XCloseDisplay(display);
    return EXIT_SUCCESS;
}